
#include "linmin.h"

#include <gsl/gsl_machine.h>

lineminimizer *lineminimizer_alloc(const lineminimizer_type *T,
                                   size_t n)
{
  lineminimizer *lm = malloc(sizeof(lineminimizer));
  
  lm->type = T;
  lm->state = malloc(T->size);
  
  (*T->alloc)(lm->state, n);
  
  return lm;
}

inline double lineminimizer_initstep_fletcher(double dphi0, double delta_f)
{
  if(dphi0 < -10.0 * GSL_DBL_EPSILON && delta_f > 10.0 * GSL_DBL_EPSILON)
    return -2.0 * delta_f / dphi0;
  else
    return 1.0;
}

int lineminimizer_minimize (lineminimizer *lm,
                            gsl_multimin_function_fdf *fdf,
                            double alpha0,
                            double eta,
                            double f,
                            gsl_vector *x,
                            gsl_vector *g,
                            gsl_vector *d,
                            double *alpha,
                            gsl_vector *x_plus,
                            double *f_plus,
                            gsl_vector *g_plus)
{
  lineminimizer_setup setup = { fdf, x, g, d, eta };
  
  (*lm->type->minimize)(lm->state, &setup, alpha0, f, alpha, x_plus, f_plus, g_plus);
  
  return GSL_SUCCESS;
}

void lineminimizer_free (lineminimizer *lm)
{
  (*lm->type->free)(lm->state);
  free(lm->state);
  free(lm);
}
